#include "Lua.h"
#include "Core.h"

extern "C" {
#include "Lua/lua.h"
#include "Lua/lauxlib.h"
#include "Lua/lualib.h"
#include "Lua/pluto.h"
}

void LuaState::Create()
{
	Destroy();
	mState = luaL_newstate();
	luaL_openlibs(mState);
	mOwn = true;
}

void LuaState::Destroy()
{
	if (mState && mOwn)
		lua_close(mState);
	mState = 0;
	mOwn = false;
}

void LuaState::LoadFile(const char* filename)
{
	CheckLuaError(luaL_loadfile(mState, filename));
	CheckLuaError(lua_pcall(mState, 0, LUA_MULTRET, 0));
	//CheckLuaError(luaL_dofile(mState, filename));
}

void LuaState::GetGlobal(const char* name)
{
	lua_getglobal(mState, name);
}

void LuaState::SetField(int index, const char* key)
{
	lua_setfield(mState, index, key);
}

void LuaState::Pop(int count)
{
	lua_pop(mState, count);
}

void LuaState::SetGlobal(const char* name)
{
	lua_setglobal(mState, name);
}

void LuaState::NewTable()
{
	lua_newtable(mState);
}

int LuaState::AsInteger(int n)
{
	return lua_tointeger(mState, n);
}

int LuaState::GetLength(int n)
{
	return lua_objlen(mState, n);
}

void LuaState::StartIteration()
{
	lua_pushnil(mState);
}

bool LuaState::Next()
{
	return lua_next(mState, -2);
}

void LuaState::GetField(int index, const char* key)
{
	lua_getfield(mState, index, key);
}

const char* LuaState::AsString(int n)
{
	if (lua_isstring(mState, n))
		return lua_tostring(mState, n);
	return "";
}

void LuaState::DoCall(int args)
{
	CheckLuaError(lua_pcall(mState, args, LUA_MULTRET, 0));
}

int LuaState::DoCallYieldable(int args)
{
	return CheckLuaError(lua_resume(mState, args));
}

int LuaState::CheckLuaError(int res)
{
	if (res != LUA_YIELD && res)
	{
		const char* str = lua_tostring(mState, -1);
		printf("Error: %s\n", str);
		Error(str);
	}
	return res;
}

void LuaState::PushInt(int v)
{
	lua_pushinteger(mState, v);
}

void LuaState::PushFunction(LuaFunction func)
{
	lua_pushcfunction(mState, func);
}

static int writer(lua_State *L, const void* p, size_t sz, void* ud)
{
	const char* d = (const char*)p;
	for (size_t i=0; i<sz; i++, d++)
		printf("%.2x", (int)*d);
	return 0;
}

void LuaState::SaveState( const char* filename )
{
	lua_newtable(mState);
	lua_getglobal(mState, "maps");
	pluto_persist(mState, writer, 0);
}

void LuaState::PushString( const char* v )
{
	lua_pushstring(mState, v);
}